import { _decorator, Node, tween, Tween, v3 } from "cc";
import { BaseUI } from "./ui.base";

const {ccclass, property} = _decorator;

@ccclass
export abstract class BasePopUp<POPUP, RETURN> extends BaseUI {
    /** 弹窗是否被关闭 */
    public get is_close(){
        return this.npromise==undefined;
    }
	private npromise: mtec.NudityPromise<RETURN>;
    private closed: boolean;
    /** 生成一个promise实例 */
    protected promise(){
        this.closed = false;
		this.npromise = new mtec.NudityPromise();
        return this.npromise.promise;
    }
    /**
     * 关闭弹窗
     * @param param 回复数据，如果不传，则会被当作弹窗操作失败传入默认参数
     */
    protected close(param?: RETURN){
        if(this.closed) return undefined;
        else this.closed = true;
        // 调用回调函数
        this.onClose(param);
        // 回复promise
        if(param!==undefined) this.npromise.resolve(param);
        else this.npromise.reject(this.default_return);
        // 清空promise相关的响应
		this.npromise = undefined;
    }

    /** 从外部关闭弹窗 */
    public closeFromOutside(){
        this.close(this.default_return);
    }

    /** 默认返回值 */
    protected abstract default_return: RETURN;
	/** 管理节点 */
	protected pop: POPUP;
	/**
	 * 显示弹窗并返回promise
	 * @param args
	 */
	public show(pop: POPUP, ...args: Parameters<typeof this.onShow>){
		this.pop = pop;
		this.node.active = true;
		this.call_func(this.onShow, ...args);
		return this.promise();
	}
    /**
     * 显示时调用
     * @param param 可选参数
     */
    public abstract onShow(...param: any[]): void;
    /** 关闭弹窗时的回调 */
    protected onClose(param: RETURN): void{};

	/**
	 * 果冻效果（入场）
	 * @param node
	 */
	protected static jelly_enter(node: Node, duration?: number){
		let np = new mtec.NudityPromise<Node>();
		Tween.stopAllByTarget(node);
		duration = duration ?? 0.5;

		tween(node)
		.set({scale: v3(0.8, 0.8, 1)})
		.to(duration, {scale: v3(1, 1, 1)}, {easing: 'elasticOut'})
		.set({scale: v3(1, 1, 1)})
		.call(()=>np.resolve(node))
		.start();

		return np.promise;
	}

	/**
	 * 果冻效果（离场）
	 * @param node
	 * @param duration
	 */
	protected static jelly_leave(node: Node, duration?: number){
		let np = new mtec.NudityPromise<Node>();
		Tween.stopAllByTarget(node);
		duration = duration ?? 0.25;

		tween(node)
		.to(duration, {scale: v3(0.8, 0.8, 1)}, {easing: "backIn"})
		.set({scale: v3(0.8, 0.8, 1)})
		.call(()=>np.resolve(node))
		.start();

		return np.promise;
	}
}
